﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Subsonic.Data;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using MichMan.Utilities;

// The Grouped Items Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234231

namespace Subsonic
{
    /// <summary>
    /// A page that displays a grouped collection of items.
    /// </summary>
    public sealed partial class GroupedItemsPage : Subsonic.Common.LayoutAwarePage
    {
        public GroupedItemsPage()
        {
            this.InitializeComponent();
            this.Loaded += GroupedItemsPage_Loaded;
            this.LayoutUpdated += GroupedItemsPage_LayoutUpdated;
        }

        Finder<ItemsPresenter> _itemsPresenter;

        private bool ItemIsVisible(FrameworkElement item)
        {
            GeneralTransform transform = TransformToVisual(item);

            Point rootPoint = transform.TransformPoint(new Point(0, 0));
            if (double.IsNaN(rootPoint.X))
                return false;
            rootPoint.X *= -1;

            double svLeft = 0; // itemGridScrollViewer.HorizontalOffset;
            double svWidth = itemGridScrollViewer.ActualWidth;
            if (double.IsNaN(svLeft) || double.IsNaN(svWidth))
                return false;
            double htLeft = rootPoint.X;
            double htWidth = item.ActualWidth;

            //Check if control is to the left of the visible area

            if (svLeft + svWidth < htLeft) return false;

            //Check if control is to the right of the visible area
            if (svLeft > htLeft + htWidth) return false;

            return true;
        }

        double _lastOffset = double.NaN;
        List<GridViewItem> _items = null;
        void GroupedItemsPage_LayoutUpdated(object sender, object e)
        {
            if (itemGridScrollViewer.HorizontalOffset == _lastOffset)
            {
                return;
            }

            if (_itemsPresenter == null || _itemsPresenter.Value() == null)
            {
                return;
            }
            _lastOffset = itemGridScrollViewer.HorizontalOffset;

            if (_items == null)
            {
                // This is reset whenever the items change.
                _items = _itemsPresenter.Value().GetDescendants().OfType<GridViewItem>().ToList();
            }

            // Go through the items and see if the image source has been updated.  
            // If not, load the new image.
            foreach (var item in _items)
            {
                if (ItemIsVisible(item))
                {
                    (item.DataContext as SampleDataItem).UpdateImage();
                }
            }
        }

        void GroupedItemsPage_Loaded(object sender, RoutedEventArgs e)
        {
            _itemsPresenter = new Finder<ItemsPresenter>(itemGridView);
            itemGridView.Items.VectorChanged += Items_VectorChanged;
        }

        void Items_VectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event)
        {
            _lastOffset = double.NaN;
            _items = null;
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.  The Parameter
        /// property provides the grouped collection of items to be displayed.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            this.DefaultViewModel["Groups"] = e.Parameter;
        }

        /// <summary>
        /// Invoked when a group header is clicked.
        /// </summary>
        /// <param name="sender">The Button used as a group header for the selected group.</param>
        /// <param name="e">Event data that describes how the click was initiated.</param>
        void Header_Click(object sender, RoutedEventArgs e)
        {
            // Determine what group the Button instance represents
            var group = (sender as FrameworkElement).DataContext;

            // Navigate to the appropriate destination page, configuring the new page
            // by passing required information as a navigation parameter
            this.Frame.Navigate(typeof(GroupDetailPage), group);
        }

        /// <summary>
        /// Invoked when an item within a group is clicked.
        /// </summary>
        /// <param name="sender">The GridView (or ListView when the application is snapped)
        /// displaying the item clicked.</param>
        /// <param name="e">Event data that describes the item clicked.</param>
        void ItemView_ItemClick(object sender, ItemClickEventArgs e)
        {
            // Navigate to the appropriate destination page, configuring the new page
            // by passing required information as a navigation parameter
            this.Frame.Navigate(typeof(ItemDetailPage), e.ClickedItem);
        }
    }
}
